<?php

/*
 * Created on 08/nov/2013
 *
 */
define('THE_SAME_AS_ARRIVED', '1');
define('INVERT_AS_ARRIVED', '2');
define('HOST_DB', 'sql.canraid.it');
define('USER_DB', 'canraidi29256');
define('PASSWORD_DB', 'canr69063');
define('DB', 'canraidi29256');
define('CHECK_BIG_LITTLE_ENDIAN', '1234567890');
$big_little_endian = THE_SAME_AS_ARRIVED;

class Pill{
	private $big_little_endian=null;
	public $checkBigLittleEndian=null;
	public $id_request=null;
	public $sum_id_request=0;
	public $STX_USERID_IDX=null;
	public $STX_MD5_PASSWORD=null;
	public $PK_SESSION=null;
	public $INT_KEY_REGISTER=null;
	public $MTX_EMAIL=null;
	
	public $type_first_contact=null;
	public $STX_CODEC_KEY=null;
	public $STX_USERID_CASE_SENSITIVE=null;
	
	public $type_operation=null;
	public $LNG_LAST_MACRO_BOUND_REFRESH=null;
	public $left_bound_latitude=null;
	public $right_bound_latitude=null;
	public $top_bound_longitude=null;
	public $bottom_bound_longitude=null;
	
	public $error=null;
	
	public $structure_pointer=array();
	
	public $bytes=null;
	
	function __construct($ble){
		$this->big_little_endian=$ble;
	}
	
	function bytes2Object(){
		$this->checkBigLittleEndian = bytes2Type($this->bytes, 1, 'I', 4, $this->big_little_endian);
		$this->id_request = bytes2Type($this->bytes, 5, 'I', 4, $this->big_little_endian);
		$len=bytes2Type($this->bytes, 9, 'I', 4, $this->big_little_endian);
		$index_base=13;
		$check_align=0;
		$counter_request_block=0;
		while ($len>=4){
			$counter_request_block++;
			$this->id_header=bytes2Type($this->bytes, $index_base, 'I', 4, $this->big_little_endian);
			if (($this->sum_id_request | $this->id_header) == 0){
				$this->sum_id_request += $this->id_header;
			}
			
			switch($this->id_header){
				case 2:
					$this->type_first_contact=bytes2Type($this->bytes, $index_base+4, 'C', 1, $this->big_little_endian);
					$this->STX_USERID_IDX=bytes2Type($this->bytes, $index_base+5, 'S', 32, $this->big_little_endian);
					$this->STX_MD5_PASSWORD=bytes2Type($this->bytes, $index_base+37, 'S', 32, $this->big_little_endian);
					$this->PK_SESSION=bytes2Type($this->bytes, $index_base+69, 'I', 4, $this->big_little_endian);
					$this->INT_KEY_REGISTER=bytes2Type($this->bytes, $index_base+73, 'I', 4, $this->big_little_endian);
					$this->MTX_EMAIL=bytes2Type($this->bytes, $index_base+77, 'S', 255, $this->big_little_endian);
					$check_align=$index_base+77+255;
					break;
				case 4:
					$this->PK_SESSION=bytes2Type($this->bytes, $index_base+4, 'I', 4, $this->big_little_endian);
					$this->type_operation=bytes2Type($this->bytes, $index_base+8, 'C', 1, $this->big_little_endian);
					$this->LNG_LAST_MACRO_BOUND_REFRESH=bytes2Type($this->bytes, $index_base+9, 'L', 8, $this->big_little_endian);
					$this->left_bound_latitude=bytes2Type($this->bytes, $index_base+17, 'L', 8, $this->big_little_endian);
					$this->right_bound_latitude=bytes2Type($this->bytes, $index_base+25, 'L', 8, $this->big_little_endian);
					$this->top_bound_longitude=bytes2Type($this->bytes, $index_base+33, 'L', 8, $this->big_little_endian);
					$this->bottom_bound_longitude=bytes2Type($this->bytes, $index_base+41, 'L', 8, $this->big_little_endian);
					$check_align=$index_base+41+8;
					break;
				case 8:
					$type_all_header=bytes2Type($this->bytes, $index_base+4, 'C', 1, $this->big_little_endian);
					$aux_msg=new Message($type_all_header);
					$aux_msg->PK_MESSAGE=bytes2Type($this->bytes, $index_base+5, 'I', 4, $this->big_little_endian);
					$aux_msg->TMS_LAST_MSG_UPDATE=bytes2Type($this->bytes, $index_base+9, 'L', 8, $this->big_little_endian);
					$aux_msg->TMS_LAST_ACTION_COMMENT=bytes2Type($this->bytes, $index_base+17, 'L', 8, $this->big_little_endian);
					$check_align=$index_base+17+8;
					if(strtoupper($type_all_header)=='A'){
						$aux_msg->LNG_LATITUDE_IDX=bytes2Type($this->bytes, $index_base+25, 'L', 8, $this->big_little_endian);
						$aux_msg->LNG_LONGITUDE_IDX=bytes2Type($this->bytes, $index_base+33, 'L', 8, $this->big_little_endian);
						$aux_msg->QTY_COMMENTS=bytes2Type($this->bytes, $index_base+41, 'L', 8, $this->big_little_endian);
						$aux_msg->QTY_LIKE=bytes2Type($this->bytes, $index_base+45, 'L', 8, $this->big_little_endian);
						$aux_msg->QTY_UNLIKE=bytes2Type($this->bytes, $index_base+49, 'L', 8, $this->big_little_endian);
						$aux_msg->i_liked_unliked_this=bytes2Type($this->bytes, $index_base+53, 'C', 1, $this->big_little_endian);
						$aux_msg->STX_USERID_CASE_SENSITIVE=bytes2Type($this->bytes, $index_base+54, 'S', 32, $this->big_little_endian);
						$aux_msg->ms_up_to_expiration=bytes2Type($this->bytes, $index_base+86, 'L', 8, $this->big_little_endian);
						$len_msg=bytes2Type($this->bytes, $index_base+94, 'I', 4, $this->big_little_endian);
						$aux_msg->LTX_MESSAGE=bytes2Type($this->bytes, $index_base+98, 'S', $len_msg, $this->big_little_endian);
						$check_align=$index_base+98+$len_msg;
					}
					array_push($this->structure_pointer, $aux_msg);
					break;
				case 16:
					$type_all_header=bytes2Type($this->bytes, $index_base+4, 'C', 1, $this->big_little_endian);
					$aux_cmt=new Comment($type_all_header);
					$aux_cmt->PK_COMMENT=bytes2Type($this->bytes, $index_base+5, 'I', 4, $this->big_little_endian);
					$aux_cmt->FK_MESSAGE=bytes2Type($this->bytes, $index_base+9, 'I', 4, $this->big_little_endian);
					$check_align=$index_base+9+4;
					if(strtoupper($type_all_header)=='A'){
						$aux_cmt->QTY_LIKE=bytes2Type($this->bytes, $index_base+13, 'I', 4, $this->big_little_endian);
						$aux_cmt->QTY_UNLIKE=bytes2Type($this->bytes, $index_base+17, 'I', 4, $this->big_little_endian);
						$aux_cmt->i_liked_unliked_this=bytes2Type($this->bytes, $index_base+21, 'C', 4, $this->big_little_endian);
						$aux_cmt->STX_USERID_CASE_SENSITIVE=bytes2Type($this->bytes, $index_base+22, 'S', 32, $this->big_little_endian);
						$len_comment=bytes2Type($this->bytes, $index_base+54, 'I', 4, $this->big_little_endian);
						$aux_cmt->LTX_COMMENT=bytes2Type($this->bytes, $index_base+58, 'S', $len_comment, $this->big_little_endian);
						$check_align=$index_base+58+$len_comment;
					}
					array_push($this->structure_pointer, $aux_cmt);
					break;
				case 32:
					$aux_lkuk=new LikeUnlike();
					$aux_lkuk->where=bytes2Type($this->bytes, $index_base+4, 'C', 1, $this->big_little_endian);
					$aux_lkuk->PK_MESSAGE=bytes2Type($this->bytes, $index_base+5, 'I', 4, $this->big_little_endian);
					$aux_lkuk->PK_COMMENT=bytes2Type($this->bytes, $index_base+9, 'I', 4, $this->big_little_endian);
					$aux_lkuk->FLC_LIKE_UNLIKE=bytes2Type($this->bytes, $index_base+13, 'C', 1, $this->big_little_endian);
					$check_align=$index_base+13+1;
					array_push($this->structure_pointer, $aux_lkuk);
					break;
				
			}
			if ($check_align + 4 <> $index_base+ $len){
				$this->error="Disallineamento checkBigLittleEndian[$checkBigLittleEndian==".CHECK_BIG_LITTLE_ENDIAN."], n-th_block[$counter_request_block], check_align[$check_align], index_base[$index_base], len[$len], header_request[$id_header]";
				return;
			}
			$index_base=$index_base+$len;
			$len = bytes2Type($this->bytes, $index_base - 4, 'I', 4, $this->big_little_endian);
		}
	}
	
	function object2Bytes(){
		$this->bytes= array();
		$this->checkBigLittleEndian = intval(CHECK_BIG_LITTLE_ENDIAN);
		type2Bytes($this->checkBigLittleEndian, 'I', $this->big_little_endian, $this->bytes);
		type2Bytes($this->id_request, 'I', $this->big_little_endian, $this->bytes);
		
		if ($this->type_first_contact != null){
			$aux_data=array();
			type2Bytes(2, 'I', $this->big_little_endian, $aux_data); //HEADER: login
			type2Bytes($this->PK_SESSION, 'I', $this->big_little_endian, $aux_data); 
			type2Bytes($this->STX_CODEC_KEY, 'S', $this->big_little_endian, $aux_data); 
			type2Bytes($this->STX_USERID_CASE_SENSITIVE, 'S', $this->big_little_endian, $aux_data); 
			$len=count($aux_data)+4;	//+4byte per inglobale il prossimo LEN
			type2Bytes($len, 'I', $this->big_little_endian, $this->bytes);  //LEN(i) del blocco attuale, inglobato nel blocco precedente (i-1)
			//nuovo blocco i//
			type2Bytes($aux_data, 'A', $this->big_little_endian, $this->bytes); 	//Header + Data
			//manca valore LEN_BLOCCO(i+1) (4byte) del prossimo blocco//
		}
		
		if ($this->type_operation != null ){
			$aux_data=array();
			type2Bytes(4, 'I', $this->big_little_endian, $aux_data); //HEADER: Operation
			type2Bytes($this->PK_SESSION, 'I', $this->big_little_endian, $aux_data); 
			type2Bytes($this->LNG_LAST_MACRO_BOUND_REFRESH, 'L', $this->big_little_endian, $aux_data); 
			$len=count($aux_data)+4;	//+4byte per inglobale il prossimo LEN
			type2Bytes($len, 'I', $this->big_little_endian, $this->bytes);	//LEN(i) del blocco attuale, inglobato nel blocco precedente (i-1)
			//nuovo blocco i//
			type2Bytes($aux_data, 'A', $this->big_little_endian, $this->bytes); 	//Header + Data
			//manca valore LEN_BLOCCO(i+1) (4byte) del prossimo blocco//
			
		}
		
		if ($this->error != null){
			$aux_data=array();
			type2Bytes(1, 'I', $this->big_little_endian, $aux_data);	 //HEADER: Error
			type2Bytes(strlen($this->error), 'I', $this->big_little_endian, $aux_data); 
			if (strlen($this->error)>0)
				type2Bytes($this->error, 'S', $this->big_little_endian, $aux_data); 
				
			$len=count($aux_data)+4;	//+4byte per inglobale il prossimo LEN
			type2Bytes($len, 'I', $this->big_little_endian, $this->bytes);	//LEN(i) del blocco attuale, inglobato nel blocco precedente (i-1)
			//nuovo blocco i//
			type2Bytes($aux_data, 'A', $this->big_little_endian, $this->bytes); 	//Header + Data
			//manca valore LEN_BLOCCO(i+1) (4byte) del prossimo blocco//
		}
		
		for($index=1; $index <= count($this->structure_pointer); $index++){
			$obj=$this->structure_pointer[$index];
			if ($obj instanceof Message || $obj instanceof Comment){
				if ($obj->type_all_header==null){
					continue;
				}
			}
			
			$aux_data=array();
			if ($obj instanceof Message){
				type2Bytes(8, 'I', $this->big_little_endian, $aux_data);	 //HEADER: Message
				type2Bytes($obj->type_all_header, 'C', $this->big_little_endian, $aux_data);
				type2Bytes($obj->PK_MESSAGE, 'I', $this->big_little_endian, $aux_data);
				type2Bytes($obj->TMS_LAST_MSG_UPDATE, 'I', $this->big_little_endian, $aux_data);
				type2Bytes($obj->TMS_LAST_ACTION_COMMENT, 'I', $this->big_little_endian, $aux_data);
				if (strtoupper($obj->type_all_header)=='A'){
					type2Bytes($obj->LNG_LATITUDE_IDX, 'L', $this->big_little_endian, $aux_data);
					type2Bytes($obj->LNG_LONGITUDE_IDX, 'L', $this->big_little_endian, $aux_data);
					type2Bytes($obj->QTY_COMMENTS, 'I', $this->big_little_endian, $aux_data);
					type2Bytes($obj->QTY_LIKE, 'I', $this->big_little_endian, $aux_data);
					type2Bytes($obj->QTY_UNLIKE, 'I', $this->big_little_endian, $aux_data);
					type2Bytes($obj->i_liked_unliked_this, 'C', $this->big_little_endian, $aux_data);
					type2Bytes($obj->STX_USERID_CASE_SENSITIVE, 'S', $this->big_little_endian, $aux_data);
					type2Bytes($obj->ms_up_to_expiration, 'L', $this->big_little_endian, $aux_data);
					type2Bytes(strlen($obj->LTX_MESSAGE), 'I', $this->big_little_endian, $aux_data);
					if (strlen($obj->LTX_MESSAGE)>0)
						type2Bytes($obj->LTX_MESSAGE, 'S', $this->big_little_endian, $aux_data);
				}
				
			}elseif ($obj instanceof Comment){
				type2Bytes(16, 'I', $this->big_little_endian, $aux_data);	 //HEADER: Comment
				type2Bytes($obj->type_all_header, 'C', $this->big_little_endian, $aux_data);
				type2Bytes($obj->PK_COMMENT, 'I', $this->big_little_endian, $aux_data);
				type2Bytes($obj->FK_MESSAGE, 'I', $this->big_little_endian, $aux_data);
				if (strtoupper($obj->type_all_header)=='A'){
					type2Bytes($obj->QTY_LIKE, 'I', $this->big_little_endian, $aux_data);
					type2Bytes($obj->QTY_UNLIKE, 'I', $this->big_little_endian, $aux_data);
					type2Bytes($obj->i_liked_unliked_this, 'C', $this->big_little_endian, $aux_data);
					type2Bytes($obj->STX_USERID_CASE_SENSITIVE, 'S', $this->big_little_endian, $aux_data);
					type2Bytes(strlen($obj->LTX_COMMENT), 'I', $this->big_little_endian, $aux_data);
					if (strlen($obj->LTX_COMMENT)>0)
						type2Bytes($obj->LTX_COMMENT, 'S', $this->big_little_endian, $aux_data);
				}
				
			}elseif ($obj instanceof LikeUnlike){
				type2Bytes(32, 'I', $this->big_little_endian, $aux_data);	 //HEADER: LikeUnlike
				type2Bytes($obj->where, 'C', $this->big_little_endian, $aux_data);
				type2Bytes($obj->PK_MESSAGE, 'I', $this->big_little_endian, $aux_data);
				type2Bytes($obj->PK_COMMENT, 'I', $this->big_little_endian, $aux_data);
				type2Bytes($obj->FLC_LIKE_UNLIKE, 'C', $this->big_little_endian, $aux_data);
			}else{
				continue;
			}
			$len=count($aux_data)+4;	//+4byte per inglobale il prossimo LEN
			type2Bytes($len, 'I', $this->big_little_endian, $this->bytes);	//LEN(i) del blocco attuale, inglobato nel blocco precedente (i-1)
			//nuovo blocco i//
			type2Bytes($aux_data, 'A', $this->big_little_endian, $this->bytes); 	//Header + Data
			//manca valore LEN_BLOCCO(i+1) (4byte) del prossimo blocco//
		}
		
		type2Bytes(0, 'I', $this->big_little_endian, $this->bytes);			//ultimo LEN mancante che chiude il msg
	}
};

class Message{
	public $type_all_header=null;
	public $PK_MESSAGE=null;
	public $TMS_LAST_MSG_UPDATE=null;
	public $TMS_LAST_ACTION_COMMENT=null;
	
	public $LNG_LATITUDE_IDX=null;
	public $LNG_LONGITUDE_IDX=null;
	
	public $QTY_COMMENTS=null;
	public $QTY_LIKE=null;
	public $QTY_UNLIKE=null;
	public $i_liked_unliked_this=null;
	public $STX_USERID_CASE_SENSITIVE=null;
	public $ms_up_to_expiration=null;
	public $LTX_MESSAGE=null;
	
	function __construct($type){
		$this->type_all_header=strtoupper($type);
	}
}

class Comment{
	public $type_all_header=null;
	public $PK_COMMENT=null;
	public $FK_MESSAGE=null;
	public $QTY_LIKE=null;
	public $QTY_UNLIKE=null;
	public $i_liked_unliked_this=null;
	public $STX_USERID_CASE_SENSITIVE=null;
	public $LTX_COMMENT=null;
	
	function __construct($type){
		$this->type_all_header=strtoupper($type);
	}
}

class LikeUnlike{
	public $where=null;
	public $PK_MESSAGE=null;
	public $PK_COMMENT=null;
	public $FLC_LIKE_UNLIKE=null;
}

function bytes2Type($array, $start, $type, $lenPassed, $big_little_endian) {
	$first = $start;
	$direction = +1;
	$len = $lenPassed;
	switch (strtoupper($type)) {
		case 'I' :
			$len = 4;
			break;
		case 'L' :
			$len = 8;
			break;
		case 'C' :
			$len = 1;
			break;
		
	}
	$last = $start + $len -1; // {1,2,3,4} ==> 1<<0, 2<<8, 3<<16, 4<<24 ==> 4321  
	switch (strtoupper($type)) {
		case 'I' :
		case 'L' :
			if (THE_SAME_AS_ARRIVED == $big_little_endian) { // {1,2,3,4} ==> 4<<0, 3<<8, 2<<16, 1<<24 ==> 1234  
				$first = $last;
				$direction = -1;
				$last = $start;
			}
			$ret = 0;
			for ($i = 0; $i < $len; $i++) {
				$ret += $array[$first + ($i * $direction)] << $i * 8;
			}
			break;
		default :
			$ret = "";
			for ($i = 0; $i < $len; $i++) {
				$ret .= chr($array[$start + $i]);
			}
			break;
	}
	return $ret;
}

function type2Bytes($value, $type, $big_little_endian,&$array_destination) {
	$aux_value=$value;
	if ($aux_value==null){
		$aux_value=0;
	}
	$last = 1;
	$direction = -1;
	switch (strtoupper($type)) {
		case 'I' :	//INT
			$data=unpack('C*', $aux_value);
			$len = 4;
			break;
		case 'L' :	//LONG
			$data=unpack('C*', $aux_value);
			$len = 8;
			break;
		case 'C' :	//CHAR
			$data=unpack('C*', $aux_value);
			$len = 1;
			break;
		case 'A':	//ARRAY
			$data=$value;
			$len = count($data);
			break;
		default:	//STRING,...
			$data=unpack('C*', $aux_value);
			$len = count($data);
			break;
		
	}
	$first = $len ; // {1,2,3,4} ==> 4321  =====Riconvertire====> array=1+2+3+4 ==> {1,2,3,4}
	switch (strtoupper($type)) {
		case 'I' :
		case 'L' :
			if (THE_SAME_AS_ARRIVED == $big_little_endian) {
				$aux_first = $first; 
				$first = $last;// {1,2,3,4} ==> 1234    =====Riconvertire====> array=1+2+3+4 ==> {1,2,3,4}
				$last = $aux_first;
				$direction = +1;
			}
			for ($i = 0; $i < $len; $i++) {
				array_push($array_destination, $data[$first + ($i * $direction)]);
			}
			break;
		default :
			for ($i = 1; $i <= $len; $i++) {
				array_push($array_destination,  $data[$i]);
			}
			break;
	}
	return $len;
}

try {
	$in_stream = file_get_contents('php://input');
	$in_byte = unpack('C*', $in_stream);
	$p=new Pill($big_little_endian);
	$p->bytes = $in_byte;
	$p->bytes2Object();
//	var_dump($p);

//var_dump($p->bytes);
        $p->bytes=null;
	$p->object2Bytes();
var_dump($p->bytes);
//      $out_stream='';
//	for ($index=1; $index <= count($p->bytes); $index++){
//		$out_stream .= $p->bytes[$index];
//	}
//	echo $out_stream;

	
//	echo 'text: >' . $in_stream . '<' . "\n";
//	$in_byte = unpack('C*', $in_stream);
//	echo 'long array IN : >' . count($in_byte) . '<' . "\n";
//	
//	$s = bytes2Type($in_byte, 1, 'S', 5, $big_little_endian);
//	$i = bytes2Type($in_byte, 6, 'I', 4, $big_little_endian);
//	$l = bytes2Type($in_byte, 10, 'L', 8, $big_little_endian);
//	$c = bytes2Type($in_byte, 18, 'C', 1, $big_little_endian);
//	echo 'STRING: >' . $s . '<' . "\n";
//	echo 'INTEGER: >' .$i . '<' . "\n";
//	echo 'LONG: >' . $l . '<' . "\n";
//	echo 'CHAR: >' . $c . '<' . "\n";

//	$con = mysql_connect(HOST_DB, USER_DB, PASSWORD_DB);
//	$db_selected = mysql_select_db(DB, $con);
//	$query="INSERT INTO PROVA (INT_, LONG_, CHAR_, VARCHAR_) VALUES ($i, $l, '$c', '$s')";
//	$retval = mysql_query($query);
//	if (! $retval){
//		echo 'Query error: '.mysql_error();
//	}
//	mysql_close($con);
} catch (Exception $e) {
	echo 'Caught exception: ', $e->getMessage(), "\n";
}
?>		